<?php
namespace ZyucMini\Core;

use ZyucMini\Core\File;

/**
 * 目录操作类 - 负责目录的创建、删除、遍历等操作
 * 提供安全的目录操作功能
 */
class Dir {

    /**
     * 检查目录是否存在
     * @param string $path 目录路径
     * @return bool
     */
    public static function exists($path) {
        return is_dir($path);
    }

    /**
     * 创建目录
     * @param string $path 目录路径
     * @param int $permissions 目录权限 (默认0755)
     * @return bool
     * @throws \Exception
     */
    public static function create($path, $permissions = 0755) {
        self::validatePath($path);
        
        if (self::exists($path)) {
            return true;
        }
        
        if (!mkdir($path, $permissions, true)) {
            throw new \Exception("ZyucMini\Core\Dir Error: failed to create directory: $path");
        }
        
        return true;
    }

    /**
     * 递归删除目录及其内容
     * @param string $path 目录路径
     * @return bool
     * @throws \Exception
     */
    public static function delete($path) {
        self::validatePath($path);
        
        if (!self::exists($path)) {
            return true;
        }
        
        $files = array_diff(scandir($path), ['.', '..']);
        foreach ($files as $file) {
            $fullPath = $path . DIRECTORY_SEPARATOR . $file;
            if (self::exists($fullPath)) {
                self::delete($fullPath);
            } else {
                File::delete($fullPath);
            }
        }
        
        if (!rmdir($path)) {
            throw new \Exception("ZyucMini\Core\Dir Error: failed to delete directory: $path");
        }
        
        return true;
    }

    /**
     * 列出目录下的所有文件和子目录
     * @param string $path 目录路径
     * @param bool $recursive 是否递归列出子目录内容
     * @param array $filters 文件过滤器 (可选)
     * @return array
     * @throws \Exception
     */
    public static function listAll($path, $recursive = false, $filters = []) {
        self::validatePath($path);
        
        if (!self::exists($path)) {
            throw new \Exception("ZyucMini\Core\Dir Error: directory not found: $path");
        }
        
        $items = array_diff(scandir($path), ['.', '..']);
        $result = [];
        
        foreach ($items as $item) {
            $fullPath = $path . DIRECTORY_SEPARATOR . $item;
            
            // 应用过滤器
            if (!empty($filters) && !self::matchesFilters($fullPath, $filters)) {
                continue;
            }
            
            $result[] = $fullPath;
            
            if (self::exists($fullPath) && $recursive) {
                $result = array_merge($result, self::listAll($fullPath, $recursive, $filters));
            }
        }
        
        return $result;
    }
    
    /**
     * 复制目录
     * @param string $source 源目录
     * @param string $destination 目标目录
     * @return bool
     * @throws \Exception
     */
    public static function copy($source, $destination) {
        self::validatePath($source);
        self::validatePath($destination);
        
        if (!self::exists($source)) {
            throw new \Exception("ZyucMini\Core\Dir Error: source directory not found: $source");
        }
        
        if (!self::exists($destination)) {
            self::create($destination);
        }
        
        $items = array_diff(scandir($source), ['.', '..']);
        
        foreach ($items as $item) {
            $sourcePath = $source . DIRECTORY_SEPARATOR . $item;
            $destPath = $destination . DIRECTORY_SEPARATOR . $item;
            
            if (self::exists($sourcePath)) {
                self::copy($sourcePath, $destPath);
            } else {
                File::copy($sourcePath, $destPath);
            }
        }
        
        return true;
    }
    
    /**
     * 移动目录
     * @param string $source 源目录
     * @param string $destination 目标目录
     * @return bool
     * @throws \Exception
     */
    public static function move($source, $destination) {
        self::validatePath($source);
        self::validatePath($destination);
        
        if (!self::exists($source)) {
            throw new \Exception("ZyucMini\Core\Dir Error: source directory not found: $source");
        }
        
        if (self::exists($destination)) {
            throw new \Exception("ZyucMini\Core\Dir Error: destination directory already exists: $destination");
        }
        
        if (!rename($source, $destination)) {
            throw new \Exception("ZyucMini\Core\Dir Error: failed to move directory from $source to $destination");
        }
        
        return true;
    }
    
    /**
     * 获取目录大小
     * @param string $path 目录路径
     * @return int 目录大小(字节)
     * @throws \Exception
     */
    public static function getSize($path) {
        self::validatePath($path);
        
        if (!self::exists($path)) {
            throw new \Exception("ZyucMini\Core\Dir Error: directory not found: $path");
        }
        
        $size = 0;
        $items = array_diff(scandir($path), ['.', '..']);
        
        foreach ($items as $item) {
            $fullPath = $path . DIRECTORY_SEPARATOR . $item;
            
            if (self::exists($fullPath)) {
                $size += self::getSize($fullPath);
            } else {
                $size += filesize($fullPath);
            }
        }
        
        return $size;
    }
    
    /**
     * 验证路径安全性
     * @param string $path 路径
     * @throws \Exception
     */
    protected static function validatePath($path) {
        if (empty($path)) {
            throw new \Exception("ZyucMini\Core\Dir Error: path cannot be empty");
        }
        
        // 检查路径遍历攻击
        if (strpos($path, '..') !== false) {
            throw new \Exception("ZyucMini\Core\Dir Error: path traversal detected in: $path");
        }
        
        // 检查绝对路径长度
        $realPath = realpath(dirname($path));
        if ($realPath === false) {
            throw new \Exception("ZyucMini\Core\Dir Error: invalid path: $path");
        }
    }
    
    /**
     * 检查路径是否匹配过滤器
     * @param string $path 路径
     * @param array $filters 过滤器
     * @return bool
     */
    protected static function matchesFilters($path, $filters) {
        if (empty($filters)) {
            return true;
        }
        
        $filename = basename($path);
        
        // 扩展名过滤
        if (isset($filters['extensions'])) {
            $ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
            if (!in_array($ext, $filters['extensions'])) {
                return false;
            }
        }
        
        // 文件名模式过滤
        if (isset($filters['pattern'])) {
            if (!preg_match($filters['pattern'], $filename)) {
                return false;
            }
        }
        
        // 排除模式
        if (isset($filters['exclude'])) {
            if (preg_match($filters['exclude'], $filename)) {
                return false;
            }
        }
        
        return true;
    }
}